package com.unrarme.api.kinobazaapi
{
	import com.adobe.serialization.json.JSON;
	import com.hurlant.crypto.Crypto;
	import com.hurlant.crypto.hash.HMAC;
	import com.hurlant.util.Base64;
	import com.hurlant.util.Hex;
	
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.LocationChangeEvent;
	import flash.geom.Rectangle;
	import flash.media.StageWebView;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
	import flash.utils.ByteArray;
	
	import mx.utils.UIDUtil;
	
	import org.iotashan.oauth.OAuthConsumer;
	import org.iotashan.oauth.OAuthRequest;
	import org.iotashan.oauth.OAuthSignatureMethod_HMAC_SHA1;
	import org.iotashan.oauth.OAuthToken;
	import org.iotashan.utils.URLEncoding;
	
	public class Kinobaza extends EventDispatcher
	{
		private var apiUrl:String = "http://api.kinobaza.tv/";
		
		private var _stage:Stage;
		
		private var _consumerKey:String;
		private var _consumerSecret:String;
		
		private var requestTokenUrl:String = "http://api.kinobaza.tv/auth/request-token";
		private var authorizeUrl:String = "http://api.kinobaza.tv/auth/authorize";
		private var authorizeCallbackUrl:String = "http://unrar.me/aspen";
		private var accessTokenUrl:String = "http://api.kinobaza.tv/auth/access-token";
		
		private var token:OAuthToken = new OAuthToken();
		private var consumer:OAuthConsumer;
		private var signatureMethod:OAuthSignatureMethod_HMAC_SHA1 = new OAuthSignatureMethod_HMAC_SHA1();
		
		private var _ws:StageWebView;
		
		public function Kinobaza(stage:Stage, target:IEventDispatcher=null)
		{
			this._stage = stage;
			super(target);
		}
		
		
		
		
		/**
		 * Запрос списка фильмов удовлетворяющих заданным параметрам.<br/>
		 * <br/>
		 * По завершении вызывает событие KinobazaEvent.FILMS_BROWSE<br/>
		 * <br/>
		 * При установке только одного parameters.ids работает как /films/<film_id><br/>
		 * 
		 * @param parameters Объект типа KinobazaRequest
		 */ 
		public function filmsBrowse(parameters:KinobazaRequest):void {
			var request:String = parameters.createRequest();
			var uri:String = this.apiUrl + '/films/browse?'+request; 
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onFilmsBrowse);
			loader.load(new URLRequest(uri));
		}
		
		private function onFilmsBrowse(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onFilmsBrowse);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.FILMS_BROWSE);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Поиск фильма по названию<br/>
		 * По завершении вызывает событие KinobazaEvent.FILMS_SEARCH
		 * 
		 * @param query Строка запроса
		 * @param limit Количество возвращаемых результатов (default=100, max=100)
		 * @param offset Cмещение результатов относительно начала (default=0)
		 * @param fields_mask Битовая маска получаемой информации о фильме (default=1)
		 * 
		 */ 
		public function filmsSearch(query:String, limit:Number = 100, offset:Number = 0, fields_mask:Number = 1):void {
			var uri:String = this.apiUrl + 'films/search';
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var data:URLVariables = new URLVariables();
			data.query = query;
			data.limit = limit;
			data.offset = offset;
			data.fields_mask = fields_mask;
			
			request.data = data;
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onFilmsSearch);
			loader.load(request);
		}
		
		private function onFilmsSearch(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onFilmsSearch);

			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.FILMS_SEARCH);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		
		public function filmsSearchByFile(filepath:String, hash: String):void {
			
		}
		
		private function onFilmsSearchByFile(e:Event):void {
			
		}
		
		public function filmsLookup():void {
			
		}
		
		private function onFilmsLookup(e:Event):void {
			
		}
		
		/**
		 * Список сезонов сериала<br/>
		 * По завершении вызывает событие KinobazaEvent.SERIES_SEASONS
		 * 
		 * @param seriesId Идентификатор сериала
		 * 
		 */ 
		
		public function seriesSeasons(seriesId:Number):void {
			var uri:String = this.apiUrl + 'films/' +seriesId + '/seasons';
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onSeriesSeasons);
			loader.load(request);
		}
		
		private function onSeriesSeasons(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onSeriesSeasons);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.SERIES_SEASONS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Информация об одном сезоне сериала<br/>
		 * По завершении вызывает событие KinobazaEvent.SERIES_SEASON_INFO
		 * 
		 * @param seriesId Идентификатор сериала
		 * @param seasonNum Номер сезона
		 */ 
		public function seriesSeasonInfo(seriesId:Number, seasonNum:Number):void {
			var uri:String = this.apiUrl + 'films/' + seriesId + '/seasons/' + seasonNum;
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onSeriesSeasonInfo);
			loader.load(request);
		}
		
		private function onSeriesSeasonInfo(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onSeriesSeasonInfo);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.SERIES_SEASON_INFO);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список эпизодов сезона<br/>
		 * По завершении вызывает событие KinobazaEvent.SERIES_SEASON_EPISODES
		 * 
		 * @param seriesId Идентификатор сериала
		 * @param seasonNum Номер сезона
		 */ 
		public function seriesSeasonEpisodes(seriesId:Number, seasonNum:Number):void {
			var uri:String = this.apiUrl + 'films/' + seriesId + '/seasons/' + seasonNum + '/episodes';
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onSeriesSeasonEpisodes);
			loader.load(request);
		}
		
		private function onSeriesSeasonEpisodes(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onSeriesSeasonEpisodes);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.SERIES_SEASON_EPISODES);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Информация об одном эпизоде<br/>
		 * По завершении вызывает событие KinobazaEvent.SERIES_EPISODE
		 * 
		 * @param seriesId Идентификатор сериала
		 * @param seasonNum Номер сезона
		 * @param episodeNum Номер эпизода
		 */ 
		public function seriesEpisode(seriesId:Number, seasonNum:Number, episodeNum:Number):void {
			var uri:String = this.apiUrl + 'films/' + seriesId + '/seasons/' + seasonNum + '/episodes/' + episodeNum;
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onSeriesEpisode);
			loader.load(request);
		}
		
		private function onSeriesEpisode(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onSeriesEpisode);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.SERIES_EPISODE);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список известных раздач серии сериала на трекерах<br/>
		 * По завершении вызывает событие KinobazaEvent.SERIES_EPISODE_TORRENTS
		 * 
		 * @param seriesId Идентификатор сериала
		 * @param seasonNum Номер сезона
		 * @param episodeNum Номер эпизода
		 */ 
		public function seriesEpisodeTorrents(seriesId:Number, seasonNum:Number, episodeNum:Number):void {
			var uri:String = this.apiUrl + 'films/' + seriesId + '/seasons/' + seasonNum + '/episodes/' + episodeNum + '/torrents';
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onSeriesEpisodeTorrents);
			loader.load(request);
		}
		
		private function onSeriesEpisodeTorrents(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onSeriesEpisodeTorrents);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.SERIES_EPISODE_TORRENTS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список дат выхода фильма в разных странах на разных носителях<br/>
		 * По завершении вызывает событие KinobazaEvent.FILM_RELEASES
		 * 
		 * @param id Идентификатор фильма
		 */ 
		public function filmReleases(id:Number):void {
			var uri:String = this.apiUrl + 'films/' + id + '/releases/';
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onFilmReleases);
			loader.load(request);
		}
		
		private function onFilmReleases(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onFilmReleases);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.FILM_RELEASES);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Комментарии к фильму<br/>
		 * По завершении вызывает событие KinobazaEvent.FILM_COMMENTS
		 * 
		 * @param id Идентификатор фильма
		 * @param offset смещение
		 * @param limit максимальное кол-во возвращаемых веток комментариев
		 */ 
		public function filmComments(id:Number, offset:Number = 0, limit:Number = 10):void {
			var uri:String = this.apiUrl + 'films/' + id + '/comments?offset=' + offset + '&limit=' + limit;
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onFilmComments);
			loader.load(request);
		}
		
		private function onFilmComments(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onFilmComments);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.FILM_COMMENTS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Публикация отзыва о фильме или комментария к отзыву<br/>
		 * По завершении вызывает событие KinobazaEvent.FILM_COMMENT
		 * 
		 * @param id Идентификатор фильма
		 * @param message отзыв/комментарий
		 * @param reply_to ID отзыва, к которому публикуется комментарий
		 */ 
		public function filmComment(id:Number, message:String, reply_to:Number = 0):void {
			var uri:String = this.apiUrl + 'films/' + id + '/comment/';
			
			var request:URLRequest = new URLRequest(uri);
			request.method = 'POST';
			
			var data:URLVariables = new URLVariables();
			data.message = message;
			if(reply_to != 0){
				data.reply_to = reply_to
			}
			
			request.data = data;
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onFilmComment);
			loader.load(request);
		}
		
		private function onFilmComment(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onFilmComment);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.FILM_COMMENT);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список известных раздач фильма на трекерах<br/>
		 * По завершении вызывает событие KinobazaEvent.FILM_TORRENTS
		 * 
		 * @param id Идентификатор фильма
		 * @param offset смещение относительно начала результатов (def: 0)
		 * @param limit максимальное кол-во результатов (def: 1000)
		 */ 
		public function filmTorrents(id:Number, limit:Number = 1000, offset:Number = 0):void {
			var uri:String = this.apiUrl + 'films/' + id + '/torrents?offset=' + offset + '&limit=' + limit;
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onFilmTorrents);
			loader.load(request);
		}
		
		private function onFilmTorrents(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onFilmTorrents);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.FILM_TORRENTS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * 
		 * User functions
		 * 
		 **/
		
		/**
		 * Запрашивает список фильмов помеченных пользователем определенным статусом 
		 * По завершении вызывает метод KinobazaEvent.USER_FILMS_BY_STATUS
		 * 
		 * @param parameters объект типа KinobazaRequest. Работают все параметры, кроме "type". "status" является обязательным.
		 *
		 */
		public function userFilmsByStatus(parameters:KinobazaRequest):void {
			if(parameters.request != null) {
				var uri:String = this.apiUrl + '/my/films/by-status?' + parameters.createRequest();
				
				var request:URLRequest = new URLRequest(uri);
				request.method = 'GET';
				
				var loader:URLLoader = new URLLoader();
				loader.addEventListener(Event.COMPLETE, onUserFilmsByStatus);
				loader.load(request);				
			}
		}
		
		private function onUserFilmsByStatus(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onUserFilmsByStatus);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.USER_FILMS_BY_STATUS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		
		
		public function userSeriesSeen():void {
			/*
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, resultHandler);
			var request:OAuthRequest = new OAuthRequest("GET", url, null, consumer, token);
			loader.load(new URLRequest(request.buildRequest(signatureMethod)));
			*/
			var uri:String = this.apiUrl + '/my/series/seen/';
			
			var request:URLRequest = new URLRequest((new OAuthRequest("GET", uri, null, consumer, token)).buildRequest(this.signatureMethod));
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onUserSeriesSeen);
			loader.load(request);
		}
		
		private function onUserSeriesSeen(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onUserSeriesSeen);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.USER_SERIES_SEEN);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список сериалов, которые пользователь отметил как "смотрю" 
		 * По завершении вызывает метод KinobazaEvent.USER_FILMS_BY_STATUS
		 * 
		 * @param parameters объект типа KinobazaRequest. Опциональный.
		 *
		 */
		
		public function userSeriesWatching(parameters:KinobazaRequest = null):void {
			var uri:String = this.apiUrl + '/my/series/watching';
			if(parameters != null) {
				uri += ('?' + parameters.createRequest());
			}
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onUserSeriesWatching);
			loader.load(request);
		}
		
		private function onUserSeriesWatching(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onUserSeriesWatching);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.USER_SERIES_WATCHING);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список отслеживаемых пользователем трекеров 
		 * По завершении вызывает метод KinobazaEvent.USER_TRACKERS
		 * 
		 * @param parameters объект типа KinobazaRequest. Опциональный.
		 *
		 */
		
		public function userTrackers():void {
			var uri:String = this.apiUrl + '/my/trackers';
			
			var request:URLRequest = new URLRequest((new OAuthRequest("GET", uri, null, consumer, token)).buildRequest(this.signatureMethod));
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onUserTrackers);
			loader.load(request);
		}
		
		private function onUserTrackers(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onUserTrackers);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.USER_TRACKERS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Отмечивание сериала/сезона/серии просмотренными/непросмотренными, в зависимости от переданного набора параметров 
		 * По завершении вызывает метод KinobazaEvent.USER_SERIES_STATUS
		 * 
		 * @param seriesId ID сериала. Обязательный параметр.
		 * @param season Номер сезона
		 * @param episode Номер серии
		 * @param status 0 - не смотрел, 1 - смотрел
		 * @param is_inclusive Если is_inclusive равен true - у сериала отмечаются просмотренными все серии по сезон <season> и эпизод <episode> включительно.
		 *
		 */
		
		public function userSetSeriesStatus(seriesId:Number, season:String = null, episode:String = null, status:Number = 0, is_inclusive:Boolean = false):void {
			var uri:String = this.apiUrl + '/my/series/mark-';
			if (status == 1) {
				uri += 'seen/';
			} else if (status == 0) {
				uri += 'not-seen/'
			}
			var request:URLRequest = new URLRequest(uri);
			request.method = 'POST';
			
			var data:URLVariables = new URLVariables();
			data.series_id = seriesId;
			if(season != null) {
				data.season = season;				
			}
			if(episode != null) {
				data.episode = episode;
			}
			
			if(is_inclusive) {
				data.inclusive = 'true';
			}
			request.data = data;
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onUserSetSeriesStatus);
			loader.load(request);
		}
		
		private function onUserSetSeriesStatus(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onUserSetSeriesStatus);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.USER_SERIES_STATUS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Отмечивание сериала/сезона/серии просмотренными/непросмотренными, в зависимости от переданного набора параметров 
		 * По завершении вызывает метод KinobazaEvent.USER_SERIES_STATUS
		 * 
		 * @param seriesId ID фильма
		 * @param status статус из KinobazaRequest
		 * @param rate оценка
		 *
		 */
		
		public function userSetFilmStatus(id:Number, status:String, rate:Number):void {
			var uri:String = this.apiUrl + '/my/films/set-status';
			
			var request:URLRequest = new URLRequest(uri);
			request.method = 'POST';
			
			var data:URLVariables = new URLVariables();
			data.id = id;
			data.status = status;
			data.rate = rate;
			
			request.data = data;
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onUserSetFilmStatus);
			loader.load(request);
		}
		
		private function onUserSetFilmStatus(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onUserSetFilmStatus);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.USER_FILM_STATUS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список доступных жанров 
		 * По завершении вызывает метод KinobazaEvent.COMMON_GENRES
		 */
		
		public function commonGenres():void {
			var uri:String = this.apiUrl + '/genres';
			
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onCommonGenres);
			loader.load(request);
		}
		
		private function onCommonGenres(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onCommonGenres);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.COMMON_GENRES);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список доступных стран 
		 * По завершении вызывает метод KinobazaEvent.COMMON_COUNTRIES
		 */
		
		public function commonCountries():void {
			var uri:String = this.apiUrl + '/countries';
			
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onCommonCountries);
			loader.load(request);
		}
		
		private function onCommonCountries(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onCommonCountries);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.COMMON_COUNTRIES);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список доступных трекеров 
		 * По завершении вызывает метод KinobazaEvent.COMMON_TRACKERS
		 */
		
		public function commonTrackers():void {
			var uri:String = this.apiUrl + '/trackers';
			
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onCommonTrackers);
			loader.load(request);
		}
		
		private function onCommonTrackers(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onCommonTrackers);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.COMMON_TRACKERS);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список доступных языков
		 * По завершении вызывает метод KinobazaEvent.COMMON_LANGUAGES
		 */
		
		public function commonLanguages():void {
			var uri:String = this.apiUrl + '/languages';
			
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onCommonLanguages);
			loader.load(request);
		}
		
		private function onCommonLanguages(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onCommonLanguages);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.COMMON_LANGUAGES);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		/**
		 * Список доступных трекеров 
		 * По завершении вызывает метод KinobazaEvent.COMMON_TRACKERS
		 */
		
		public function commonTorrentLink(hash:String):void {
			var uri:String = this.apiUrl + '/torrents/' + hash + '/direct-link';
			
			var request:URLRequest = new URLRequest(uri);
			request.method = 'GET';
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onCommonTorrentLink);
			loader.load(request);
		}
		
		private function onCommonTorrentLink(e:Event):void {
			(e.target as URLLoader).removeEventListener(Event.COMPLETE, onCommonTorrentLink);
			var data:Object = JSON.decode((e.target as URLLoader).data);
			
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.COMMON_TORRENT_LINK);
			if (isError(data)) {
				ke = new KinobazaEvent(KinobazaEvent.ERROR);
			}
			ke.data = data;
			dispatchEvent(ke);
		}
		
		private function isError(responseObject:Object):Boolean {
			if (responseObject.hasOwnProperty('code')) {
				return true;
			} else {
				return false;
			}
		}
		/**
		 *
		 * OAuth 
		 * app_key 2a091943b648bb1945ee596116591ba204d8768e8
		 * sec_key 729ea075966267e1abd1f6ec24b222c2
		 **/
		
		public function authenticate(consumerKey:String, consumerSecret:String):void {
			this._consumerKey = consumerKey;
			this._consumerSecret = consumerSecret;
			this.consumer = new OAuthConsumer(this._consumerKey, this._consumerSecret);
			// Getting request token
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, requestTokenHandler);
			var request:OAuthRequest = new OAuthRequest("GET", this.requestTokenUrl, null, this.consumer, null);
			var req:String = request.buildRequest(signatureMethod); 
			trace(req);
			loader.load(new URLRequest(req));
		}
		
		private function requestTokenHandler(e:Event):void {
			// Got request token
			parseToken(e.currentTarget.data);
			this._ws = new StageWebView();
			this._ws.addEventListener(LocationChangeEvent.LOCATION_CHANGE, onChange);
			this._ws.stage = this._stage;
			this._ws.viewPort = new Rectangle(0, 0, this._stage.width, this._stage.height);
			
			trace(authorizeUrl + "?oauth_token=" + token.key + "&oauth_callback=" + URLEncoding.encode(this.authorizeCallbackUrl));
			this._ws.loadURL(authorizeUrl + "?oauth_token=" + token.key + "&oauth_callback=" + URLEncoding.encode(this.authorizeCallbackUrl));
		}
		
		private function onChange(e:Event):void {
			var location:String = Object(e).location; 
			trace('Location: ' + location);
			if (location.search(/unrar/g) > -1) {
				if (location.search(/oauth_verifier/g) > -1) {
					trace("Success: " + location);
					this._ws.removeEventListener(LocationChangeEvent.LOCATION_CHANGE, onChange);
					this._ws.dispose();
					this.getAccessToken();
				} else {
					trace("Fail: " + location);
				}
				
			} else {
				trace("Wrong: " + location);
			}
		}
		
		private function getAccessToken():void
		{
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, accessTokenHandler);
			var request:OAuthRequest = new OAuthRequest("GET", accessTokenUrl, null, consumer, token);
			loader.load(new URLRequest(request.buildRequest(signatureMethod)));
		}
		
		protected function accessTokenHandler(event:Event):void 
		{
			parseToken(event.currentTarget.data);
			var ke:KinobazaEvent = new KinobazaEvent(KinobazaEvent.AUTHENTICATED);
			dispatchEvent(ke);
		}
		
		private function parseToken(response:String):Boolean 
		{
			var params:Array = response.split("&");
			for (var i:int = 0; i < params.length; i++) 
			{
				var param:String = params[i];
				var nameValue:Array = param.split("=");
				if (nameValue.length == 2) 
				{
					switch (nameValue[0]) 
					{
						case "oauth_token":
							token.key = nameValue[1];
							break;
						case "oauth_token_secret":
							token.secret = nameValue[1];
							break;
					}
				}
			}
			return true;
		}
		/*
		public function requestToken():void {
			var curDate:Date = new Date();
			var url:String = 'http://api.qa.kinobaza.tv/auth/request-token';
			var request:URLRequest = new URLRequest(url);
			request.method = 'GET';
			var data:URLVariables = new URLVariables();
			data.oauth_consumer_key = this._apiKey;
			data.oauth_timestamp = String(curDate.time).substring(0, 13);
			data.oauth_nonce = UIDUtil.getUID(curDate);
			data.oauth_signature_method = 'HMAC-SHA1';
			
			// for sign
			var forSign:String = URLEncoding.encode('GET');
			forSign += '&';
			forSign += URLEncoding.encode(url);
			forSign += '&';
			forSign += URLEncoding.encode('oauth_consumer_key=' + data.oauth_consumer_key);
			forSign += URLEncoding.encode('&');
			forSign += URLEncoding.encode('oauth_nonce=' + data.oauth_nonce);
			forSign += URLEncoding.encode('&');
			forSign += URLEncoding.encode('oauth_signature_method=' + data.oauth_signature_method);
			forSign += URLEncoding.encode('&');
			forSign += URLEncoding.encode('oauth_timestamp=' + data.oauth_timestamp);
			
			trace("ForSign: "+ forSign);
			
			var sSec:String = this._secretKey;
			var hmac:HMAC = Crypto.getHMAC("sha1");
			var key:ByteArray = Hex.toArray(Hex.fromString(sSec));
			var message:ByteArray = Hex.toArray(Hex.fromString(forSign));
			var result:ByteArray = hmac.compute(key, message);
			
			
			data.oauth_signature = Base64.encodeByteArray(result);
			
			request.data = data;
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onRequest);
			loader.load(request);
			
		}
		
		private function onRequest(e:Event):void {
			var data:Object = (e.target as URLLoader).data;
			var pairs:Array = String(data).split('&');
			var regex:RegExp = /oauth_callback_confirmed=([0-9]{1})&oauth_token=([0-9a-f]{32,50})&oauth_token_secret=([0-9a-f]{32})&kinobaza_access_pin=([0-9]{4,6})&xoauth_token_ttl=([0-9]{4,6})/g;
			var matches:Object = regex.exec(String(data));
			var oauth:Object = {"oauth_token": matches[2], "oauth_token_secret": matches[3], "kinobaza_access_pin": matches[4]}
			trace(oauth);
			//var url:String = "http://api.qa.kinobaza.tv/auth/authorize?oauth_token=" + oauth.oauth_token;
			
			var url:String = "http://api.qa.kinobaza.tv/auth/authorize?oauth_callback=swf&oauth_token=" + oauth.oauth_token;
			
		}
		*/
		
	}
}